#include "game.h"

Game::Game(int mode, const int width, const int height) : cam(Vector3f(0,0,-1), Vector3f(0,0,0), Vector3f(0,1,0)) {
	this->width = width;
	this->height = height;
	phase = PHASE_HIDE;
	gameMode = mode;
	// Initialize camera frustum
	cam.setPerspective(60, width/(float)height, 1, 3000);
	players[PLAYER_1].setPosition(Vector3f(1,1,1));
	players[PLAYER_2].setPosition(Vector3f(1,1,1));
	// Player 1 is red
	players[PLAYER_1].setColor(Vector3f(0.7,0.7,0));
	// Player 2 is blue
	players[PLAYER_2].setColor(Vector3f(0,0.7,0.7));

	initial = time(NULL);
}

void Game::reshapeFunc(int width, int height) {
	cam.setPerspective(60, width/(float)height, 1, 3000);
	this->width = width;
	this->height = height;
}

void Game::keyboardFunc(unsigned char key, int x, int y) {
	Vector3f displacement[NUM_PLAYERS];

	if(phase == PHASE_HIDE) {
		switch(key) {
			// Player 1 Keys
			case 'w':
				displacement[PLAYER_1] = Vector3f(1,0,0);
	players[0].move(players[0].getLookAt()*0.2);
				break;
			case 'a':
				displacement[PLAYER_1] = Vector3f(0,0,1);
	players[0].rotate(10);
				break;
			case 's':
				displacement[PLAYER_1] = Vector3f(-1,0,0);
	players[0].move(players[0].getLookAt()*-0.2);
				break;
			case 'd':
				displacement[PLAYER_1] = Vector3f(0,0,-1);
	players[0].rotate(-10);
				break;
		}
	}

	if(phase == PHASE_SEEK) {
		switch(key) {
			// Player 2 Keys
			case '8':
				displacement[PLAYER_2] = Vector3f(1,0,0);
	players[1].move(players[1].getLookAt()*0.2);
				break;
			case '4':
				displacement[PLAYER_2] = Vector3f(0,0,1);
	players[1].rotate(10);
				break;
			case '5':
				displacement[PLAYER_2] = Vector3f(-1,0,0);
	players[1].move(players[1].getLookAt()*-0.2);
				break;
			case '6':
				displacement[PLAYER_2] = Vector3f(0,0,-1);
	players[1].rotate(-10);
				break;
		}
	}
}

void Game::update() {
	time_t now = time(NULL);

	if(phase == PHASE_HIDE) {
		if(difftime(now, initial) >= TIME_TO_HIDE) {
			phase = PHASE_SEEK;
			initial = now;
		}
	} else {
		if(difftime(now, initial) >= TIME_TO_SEEK)
			restart();
	}
}

void Game::drawMap(const int player) {
	if((player < PLAYER_1) || (player >= NUM_PLAYERS))
		return;

	glViewport(0,height*0.75, width*0.25, height*0.25);
	glClear(GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	{
		glLoadIdentity();

		Vector3f pos = players[player].getPosition();
		Vector3f lookAt = players[player].getLookAt();

		//* World map
		cam.setPosition(Vector3f(10, 30, 10));
		cam.setTarget(Vector3f(0,-30,0), Vector3f(1,0,0));
		//*/
		cam.look();

		// Draw current player (third person)
		glPushMatrix();
		{
			glTranslatef(pos.getX(), pos.getY(), pos.getZ());
			players[player].draw();
		}
		glPopMatrix();
/*
		glBegin(GL_LINES);
			glColor3f(1,1,1);
			glVertex3f(pos.getX(), pos.getY(), pos.getZ());
			glVertex3f(pos.getX() + lookAt.getX(), pos.getY() + lookAt.getY(), pos.getZ() + lookAt.getZ());
		glEnd();
*/

		glScalef(0.5, 0.5, 0.5);
		stage.draw();
	}
	glPopMatrix();
}

void Game::draw(const int player) {
	if((player < PLAYER_1) || (player >= NUM_PLAYERS))
		return;

	//glClearColor(0, 0, 0, 1);
	glClearColor(0.9, 0.9, 0.9, 1);

	if(gameMode == SPLIT_SCREEN) {
		cam.setPerspective(60, width/(float)(2.0*height), 1, 3000);
		if(player == PLAYER_1)
			glViewport(0,0, width/2,height);
		else
			glViewport(width/2,0, width/2,height);
		glClear(GL_DEPTH_BUFFER_BIT);
	}
	else {
		cam.setPerspective(60, width/(float)height, 1, 3000);
		glViewport(0,0, width,height);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	}
	
	static const char* osdHelp[NUM_PLAYERS][NUM_PHASES] = {{"Wait while your enemy is hiding.", "Go find your enemy."}, {"Find a place to hide.", "Wait."}};
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	{
		glLoadIdentity();

		Vector3f pos = players[player].getPosition();
		Vector3f lookAt = players[player].getLookAt();

		// Configure camera position
		/* Behind player
		cam.setPosition(pos - lookAt + Vector3f(0, 0.3, 0));
		cam.setTarget(lookAt, Vector3f(0,1,0));
		//*/

		//* Top
		cam.setPosition(pos + Vector3f(0, 2, 0));
		cam.setTarget(Vector3f(0,-2,0)-lookAt*0.2, lookAt);
		//*/

		/* World map
		cam.setPosition(Vector3f(10, 30, 10));
		cam.setTarget(Vector3f(0,-30,0), Vector3f(1,0,0));
		//*/
		cam.look();

		// Draw current player (third person)
		glPushMatrix();
		{
			glTranslatef(pos.getX(), pos.getY(), pos.getZ());
			players[player].draw();
		}
		glPopMatrix();
		
		glPushMatrix();
		{
			pos = players[ENEMY(player)].getPosition();
			glTranslatef(pos.getX(), pos.getY(), pos.getZ());
			players[ENEMY(player)].draw();
		}
		glPopMatrix();

		//*
		// Draw stage
		glScalef(0.5, 0.5, 0.5);
		stage.draw();

		/* Axis
		glBegin(GL_LINES);
			glColor3f(1,0,0);
			glVertex3f(-10, 0, 0);
			glVertex3f(10, 0, 0);

			glColor3f(0,1,0);
			glVertex3f(0, 10, 0);
			glVertex3f(0, -10, 0);

			glColor3f(0,0,1);
			glVertex3f(0, 0, 10);
			glVertex3f(0, 0, -10);
		glEnd();
		//*/
	}
	glPopMatrix();

	drawMap(player);
}


void Game::restart() {
	players[PLAYER_1].setPosition(Vector3f(1,1,1));
	players[PLAYER_2].setPosition(Vector3f(1,1,1));
	phase = PHASE_HIDE;
	initial = time(NULL);
}